// type 的多种用法
package main

import (
	"fmt"
)

// 1、定义结构体
type UserInfo struct {
	Name string
}

// 2、类型重命名
type UserName string

// 定义别名 类似 type byte = uint8
type stringAlias = string

// 3、接口定义
type Reader interface {
	Read()
}

// 接口实现
func (u *UserInfo) Read() {
	fmt.Println("I can read!")
}

// 4、函数定义
type Handler func(a int, b int) int

func calculate(name string, h Handler) int {
	fmt.Println("calculate " + name)
	return h(10, 20)
}

func handlerAdd(a int, b int) int {
	return a + b
}

func main() {
	u := UserInfo{Name: "zxy"}
	fmt.Println("u:", u)

	var userName UserName
	userName = "zxy"
	fmt.Println("userName:", userName)

	var str string = "zxy"
	fmt.Println("str:", str)
	var str2 stringAlias = str
	fmt.Println("str2:", str2)
	// 重命名的不支持隐式转换，别名的可以
	//var str3 string
	//str3 = userName

	u.Read()

	ra := calculate("加法", handlerAdd)
	fmt.Println("result:", ra)

	numInterface := getNum()
	num, ok := numInterface.(*int) // nil居然也可以获取到类型
	fmt.Println(num)               // <nil>
	fmt.Println(ok)                // true

	// switch搭配.(type)，不仅可以case出类型，还能获取到数据的类型
	strInterface := getStr()
	switch data := strInterface.(type) {
	case string:
		fmt.Printf("是一个string: %s \n", data)
		break
	case int:
		fmt.Printf("是一个int: %d \n", (data * 10))
		break
	}
}

func getNum() interface{} {
	var num *int = nil
	return num
}

func getStr() interface{} {
	return "abc"
	//return 12
}
